﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Teal.Compiler {

    /// <summary>
    /// 表示一个编译器。用于存储相关的配置数据以及提供公共的编译辅助函数。
    /// </summary>
    public static partial class Compiler {

        /// <summary>
        /// 获取或设置当前编译器使用的配置。
        /// </summary>
        public static CompilerOptions options = new CompilerOptions();

        /// <summary>
        /// 添加一个要编译的源。
        /// </summary>
        /// <param name="path"></param>
        /// <param name="startLocation"></param>
        /// <param name="endLocation"></param>
        public static void addSource(string path, Location startLocation = default(Location), Location endLocation = default(Location)) {

            path = Path.GetFullPath(path);

            // 解析为文件夹。
            if (Directory.Exists(path)) {
                foreach (var file in Directory.GetFiles(path, "*.teal", SearchOption.AllDirectories)) {
                    if (!Compiler.options.sourceFiles.Contains(file)) {
                        Compiler.options.sourceFiles.Add(file);
                    }
                }
                return;
            }

            // 解析为文件。
            if (File.Exists(path)) {
                if (!Compiler.options.sourceFiles.Contains(path)) {
                    Compiler.options.sourceFiles.Add(path);
                }
                return;
            }

            Compiler.error(ErrorCode.sourceNotFound, String.Format("找不到文件或文件夹“{0}”", path), startLocation, endLocation);
        }

        /// <summary>
        /// 解析并应用指定设置。
        /// </summary>
        /// <param name="key">设置的字段名。</param>
        /// <param name="value">设置的值。</param>
        /// <param name="startLocation">设置的起始位置。</param>
        /// <param name="endLocation">设置的结束位置。</param>
        public static void applyOption(string key, string value, Location startLocation = default(Location), Location endLocation = default(Location)) {
            switch (key) {

                #region out
                case "out":
                    if (string.IsNullOrEmpty(value)) {
                        Compiler.error(ErrorCode.expectedOutParam, "“out”配置的值应为文件名", startLocation, endLocation);
                        return;
                    }
                    options.outputPath = Path.GetFullPath(value);
                    return;
                #endregion

                #region define
                case "define": {
                        string defineName, defineValue;
                        splitArgument(value, out defineName, out defineValue);

                        if (!Unicode.isIdentifier(defineName)) {
                            Compiler.error(ErrorCode.invalidDefineName, String.Format("名称“{0}”不是合法的宏名；宏名应该是标识符", defineName), startLocation, endLocation);
                            return;
                        }

                        switch (defineValue) {
                            case null:
                            case "true":
                                Compiler.options.defines.Add(value);
                                break;
                            case "false":
                                Compiler.options.defines.Remove(value);
                                break;
                            default:
                                Compiler.error(ErrorCode.none, String.Format("宏值只能是“true”或“false”；“{0}”不是有效的宏值", defineValue), startLocation, endLocation);
                                break;
                        }

                        return;
                    }
                #endregion

                #region target
                case "target":
                    switch (value) {
                        case "lib":
                            Compiler.options.targetType = CompileTargetType.lib;
                            break;
                        case "app":
                            Compiler.options.targetType = CompileTargetType.app;
                            break;
                        case "console":
                            Compiler.options.targetType = CompileTargetType.console;
                            break;
                        case "win32Console":
                            Compiler.options.targetType = CompileTargetType.win32Console;
                            break;
                        case "win32App":
                            Compiler.options.targetType = CompileTargetType.win32App;
                            break;
                        case "win32Lib":
                            Compiler.options.targetType = CompileTargetType.win32Lib;
                            break;
                        case "web":
                            Compiler.options.targetType = CompileTargetType.web;
                            break;
                        default:
                            Compiler.error(ErrorCode.none, String.Format("“target”配置的值应为“lib”、“app”、“console”、“web”、“win32Console”、“win32App”或“win32Lib”；“{0}”不是有效的编译目标", value), startLocation, endLocation);
                            break;
                    }
                    return;
                #endregion

                #region encoding
                case "encoding":
                    switch (value) {
                        case "utf8":
                            Compiler.options.sourceEncoding = System.Text.Encoding.UTF8;
                            break;
                        case "default":
                            Compiler.options.sourceEncoding = System.Text.Encoding.Default;
                            break;
                        default:
                            try {
                                Compiler.options.sourceEncoding = System.Text.Encoding.GetEncoding(value);
                            } catch {
                                Compiler.error(ErrorCode.none, String.Format("“encoding”配置的值应为编码名；“{0}”不是有效的编码名", value), startLocation, endLocation);
                            }
                            break;
                    }
                    return;
                #endregion

                #region languageversion
                case "languageversion":
                    switch (value) {
                        case "default":
                            Compiler.options.languageVersion = LanguageVersion.latest;
                            break;
                        case "1":
                            Compiler.options.languageVersion = LanguageVersion.ISO_1;
                            break;
                        default:
                            Compiler.error(ErrorCode.none, String.Format("“tealversion”配置的值应为“default”或“1”；“{0}”不是有效的语言版本", value), startLocation, endLocation);
                            break;
                    }
                    return;
                #endregion

                #region sdkversion
                case "sdkversion":
                    switch (value) {
                        case "default":
                            Compiler.options.sdkVersion = SdkVersion.latest;
                            break;
                        case "1":
                            Compiler.options.sdkVersion = SdkVersion.v1;
                            break;
                        default:
                            Compiler.error(ErrorCode.none, String.Format("“runtime”配置的值应为“default”或“1”；“{0}”不是有效的运行时版本", value), startLocation, endLocation);
                            break;
                    }
                    return;
                #endregion

                #region warn
                case "warn":
                    int level;
                    if (!int.TryParse(value, out level) || level < (int)WarningLevel.lowest || level > (int)WarningLevel.highest) {
                        Compiler.error(ErrorCode.expectedOutParam, String.Format("“warn”配置的值应在 0 到 4 之间；“{0}”不是有效的值", value), startLocation, endLocation);
                        return;
                    }

                    Compiler.options.warningLevel = (WarningLevel)level;
                    return;

                #endregion

                #region warning
                case "warning": {
                        string warningId, warningValue;
                        splitArgument(value, out warningId, out warningValue);
                        int id;
                        if (!int.TryParse(warningId, out id)) {
                            Compiler.error(ErrorCode.none, String.Format("“{0}”不是有效的警告号", warningId), startLocation, endLocation);
                            return;
                        }
                        if (warningValue == "false") {
                            if (Compiler.options.disabledWarnings == null)
                                Compiler.options.disabledWarnings = new HashSet<ErrorCode>();
                            Compiler.options.disabledWarnings.Add((ErrorCode)id);
                        } else if (Compiler.options.disabledWarnings != null) {
                            Compiler.options.disabledWarnings.Remove((ErrorCode)id);
                        }
                        return;
                    }
                #endregion

                #region optimize
                case "optimize":
                    switch (value) {
                        case null:
                        case "basic":
                            Compiler.options.optimize = OptimizeLevel.basic;
                            break;
                        case "none":
                            Compiler.options.optimize = OptimizeLevel.none;
                            break;
                        case "all":
                            Compiler.options.optimize = OptimizeLevel.all;
                            break;
                        default:
                            Compiler.error(ErrorCode.none, String.Format("“optimize”配置的值应为“none”、“basic”、或“all”；“{0}”不是有效的优化配置", value), startLocation, endLocation);
                            break;
                    }
                    return;

                #endregion

                #region resource
                case "resource": {
                        string resourceName, resourcePath;
                        splitArgument(value, out resourceName, out resourcePath);
                        if (resourcePath == null) {
                            resourcePath = resourceName;
                        }

                        if (string.IsNullOrEmpty(resourcePath)) {
                            Compiler.error(ErrorCode.expectedOutParam, "“resource”配置的值应为文件名", startLocation, endLocation);
                            return;
                        }

                        resourcePath = Path.GetFullPath(resourcePath);

                        if (!File.Exists(resourcePath)) {
                            Compiler.error(ErrorCode.expectedOutParam, String.Format("无法找到资源文件“{0}”", resourcePath, startLocation, endLocation));
                            return;
                        }

                        if (Compiler.options.embedResources == null) {
                            Compiler.options.embedResources = new Dictionary<string, string>();
                        }

                        if (Compiler.options.embedResources.ContainsKey(resourceName)) {
                            Compiler.error(ErrorCode.expectedOutParam, String.Format("资源名称“{0}”已存在", resourceName), startLocation, endLocation);
                            return;
                        }

                        Compiler.options.embedResources.Add(resourceName, resourcePath);
                        return;
                    }
                #endregion

                #region include
                case "include":
                    addSource(value, startLocation, endLocation);
                    return;
                #endregion

                #region exclude
                case "exclude":
                    Compiler.options.sourceFiles.Remove(Path.GetFullPath(value));
                    return;

                #endregion

                #region import
                case "import": {

                        string libName, libPath;
                        splitArgument(value, out libName, out libPath);
                        if (libPath == null) {
                            libPath = libName;
                            libName = null;
                        }

                        if (string.IsNullOrEmpty(libPath)) {
                            Compiler.error(ErrorCode.expectedOutParam, "“import”配置的值应为文件名", startLocation, endLocation);
                            return;
                        }

                        if (!File.Exists(libPath)) {
                            Compiler.error(ErrorCode.expectedOutParam, String.Format("无法找到导入文件“{0}”", libPath, startLocation, endLocation));
                            return;
                        }

                        Compiler.options.importedLibs.Add(new ImportedLibarayInfo() {
                            alias = libName,
                            path = libPath
                        });
                        return;
                    }
                #endregion

                #region doc
                case "doc":
                    if (string.IsNullOrEmpty(value)) {
                        Compiler.options.docOutputPath = String.Empty;
                        return;
                    }
                    Compiler.options.docOutputPath = value;
                    return;
                #endregion

                #region debug
                case "debug":
                    if (string.IsNullOrEmpty(value)) {
                        Compiler.options.debugOutputPath = String.Empty;
                        return;
                    }
                    Compiler.options.debugOutputPath = value;
                    return;
                #endregion

                #region win32resource
                case "win32resource":
                    if (string.IsNullOrEmpty(value)) {
                        Compiler.error(ErrorCode.expectedOutParam, "“win32resource”配置的值应为文件名", startLocation, endLocation);
                        return;
                    }
                    if (Compiler.options.win32Icon != null) {
                        Compiler.error(ErrorCode.none, "无法同时指定“win32resource”和“win32icon”配置项");
                        return;
                    }
                    Compiler.options.win32Resource = value;
                    return;
                #endregion

                #region win32icon
                case "win32icon":
                    if (string.IsNullOrEmpty(value)) {
                        Compiler.error(ErrorCode.expectedOutParam, "“win32icon”配置的值应为文件名", startLocation, endLocation);
                        return;
                    }
                    if (Compiler.options.win32Resource != null) {
                        Compiler.error(ErrorCode.none, "无法同时指定“win32resource”和“win32icon”配置项");
                        return;
                    }
                    Compiler.options.win32Icon = value;
                    return;
                #endregion

                #region main
                case "main":
                    if (string.IsNullOrEmpty(value)) {
                        Compiler.error(ErrorCode.expectedOutParam, "“main”配置的值应为类名", startLocation, endLocation);
                        return;
                    }

                    Compiler.options.mainClass = value;
                    return;
                #endregion

                #region lib
                case "lib":
                    if (string.IsNullOrEmpty(value)) {
                        Compiler.error(ErrorCode.expectedOutParam, "“lib”配置的值应为文件名", startLocation, endLocation);
                        return;
                    }
                    Compiler.options.ReferencesLookupPaths.Add(value);
                    return;
                #endregion

                #region strict
                case "strict": {
                        string strictName, strictValue;
                        splitArgument(value, out strictName, out strictValue);
                        bool isFalse = strictValue == "false";
                        switch (strictName) {
                            case "ptr":
                                Compiler.options.disallowUnsafeCode = isFalse;
                                break;
                            case "varAsObject":
                                Compiler.options.disallowVarAsObject = isFalse;
                                break;
                            case "semicolons":
                                Compiler.options.disallowMissingSemicolons = isFalse;
                                break;
                            case "parentheses":
                                Compiler.options.disallowMissingParentheses = isFalse;
                                break;
                            case "emptyFunc":
                                Compiler.options.disallowMissingFuncBody = isFalse;
                                break;
                            default:
                                Compiler.options.disallowUnsafeCode =
                                    Compiler.options.disallowVarAsObject =
                                    Compiler.options.disallowMissingSemicolons =
                                    Compiler.options.disallowMissingParentheses =
                                    Compiler.options.disallowMissingFuncBody =
                                    strictName == "false";
                                break;
                        }
                        return;
                    }
                #endregion

                #region platform
                case "platform":
                    switch (value) {
                        case "all":
                            Compiler.options.targetPlatform = CompileTargetPlatform.all;
                            break;
                        case "arm":
                            Compiler.options.targetPlatform = CompileTargetPlatform.arm;
                            break;
                        case "x86":
                            Compiler.options.targetPlatform = CompileTargetPlatform.x86;
                            break;
                        case "x64":
                            Compiler.options.targetPlatform = CompileTargetPlatform.x64;
                            break;
                        case "itanium":
                            Compiler.options.targetPlatform = CompileTargetPlatform.ia64;
                            break;
                        case "all32bitpreferred":
                            Compiler.options.targetPlatform = CompileTargetPlatform.all32Preferred;
                            break;
                        default:
                            Compiler.error(ErrorCode.none, String.Format("“platform”配置的值应为“all”、“arm”、“x86”、“x64”、“itanium”或“all32bitpreferred”；“{0}”不是有效的编译目标", value), startLocation, endLocation);
                            break;
                    }
                    return;
                #endregion

                #region rootpath
                case "rootpath":
                    Compiler.options.rootPath = value;
                    return;
                #endregion

                #region corelib
                case "corelib":
                    Compiler.options.isCompilingCoreLib = value != "false";
                    return;
                #endregion

                #region 其它
                default:
                    Compiler.error(ErrorCode.invalidDefineName, String.Format("“{0}”不是无效的配置字段", key));
                    break;
                #endregion

            }
        }

        private static void splitArgument(string argument, out string name, out string value) {
            var eq = argument.IndexOf('=');

            if (eq < 0) {
                name = argument;
                value = null;
            } else {
                name = argument.Substring(0, eq).TrimEnd();
                value = argument.Substring(eq + 1).TrimStart();
            }
        }

        /// <summary>
        /// 检查所有配置是否都合法。
        /// </summary>
        /// <returns></returns>
        public static bool checkOptions() {

            if (Compiler.options.sourceFiles.Count == 0 && Compiler.options.targetType != CompileTargetType.lib && Compiler.options.targetType != CompileTargetType.win32Lib) {
                Compiler.error(ErrorCode.none, "未指定任何源文件");
                return false;
            }

            if (Compiler.options.targetPlatform == CompileTargetPlatform.all32Preferred && (Compiler.options.targetType == CompileTargetType.lib || Compiler.options.targetType == CompileTargetType.win32Lib)) {
                Compiler.error(ErrorCode.none, "只有生成可执行文件时才能设置生成目标为“all32Preferred”");
                return false;
            }

            // 自动生成输出路径。
            if (options.outputPath == null) {
                string ext;

                switch (options.targetType) {
                    case CompileTargetType.win32Lib:
                        ext = ".dll";
                        break;
                    case CompileTargetType.win32App:
                    case CompileTargetType.win32Console:
                        ext = ".exe";
                        break;
                    case CompileTargetType.app:
                    case CompileTargetType.console:
                        ext = ".texe";
                        break;
                    case CompileTargetType.lib:
                        ext = ".tlib";
                        break;
                    default:
                        ext = null;
                        break;
                }

                if (Compiler.options.sourceFiles.Count == 0) {
                    Compiler.error(ErrorCode.none, "在未指定任何源文件时必须指定输出文件");
                    return false;
                }

                options.outputPath = Path.ChangeExtension(Compiler.options.sourceFiles[0], ext);

            } else if(Compiler.options.outputPath.IndexOfAny(Path.GetInvalidPathChars()) >= 0){
                Compiler.error(ErrorCode.none, String.Format("“{0}”不是有效的输出文件路径；路径中包含非法字符", Compiler.options.outputPath));
                return false;
            }

            if (Compiler.options.debugOutputPath == String.Empty) {
                Compiler.options.debugOutputPath = Path.ChangeExtension(Compiler.options.debugOutputPath, ".tdbg");
            }

            if (Compiler.options.docOutputPath == String.Empty) {
                Compiler.options.docOutputPath = Path.ChangeExtension(Compiler.options.outputPath, ".tdoc");
            }

            return true;
        }

    }

    /// <summary>
    /// 存储编译器配置。
    /// </summary>
    public sealed class CompilerOptions {
        #region 暂时不能删除

        public bool EnhancedWarnings;
        public bool LoadDefaultReferences;
        public string SdkVersion;

        //
        // Modules to be embedded
        //
        public List<string> Modules;

        //
        // Lookup paths for referenced assemblies
        //
        public List<string> ReferencesLookupPaths;

        //
        // If true, the compiler is operating in statement mode,
        // this currently turns local variable declaration into
        // static variables of a class
        //
        public bool StatementMode;	// TODO: SUPER UGLY

        readonly List<SourceFile2> source_files;


        //
        // Whether we are being linked against the standard libraries.
        // This is only used to tell whether `System.Object' should
        // have a base class or not.
        //
        public bool StdLib;

        public string RuntimeMetadataVersion;

        List<int> warnings_as_error;
        List<int> warnings_only;

        public CompilerOptions() {
            StdLib = true;
            
            LoadDefaultReferences = true;

            Modules = new List<string>();
            ReferencesLookupPaths = new List<string>();

            source_files = new List<SourceFile2>();
        }

        #region Properties

        public SourceFile2 FirstSourceFile {
            get {
                return source_files.Count > 0 ? source_files[0] : null;
            }
        }

        public bool NeedsEntryPoint {
            get {
                return targetType == CompileTargetType.win32Console || targetType == CompileTargetType.win32App;
            }
        }

        public List<SourceFile2> SourceFiles {
            get {
                return source_files;
            }
        }

        #endregion

        public void AddWarningAsError(int id) {
            if (warnings_as_error == null)
                warnings_as_error = new List<int>();

            warnings_as_error.Add(id);
        }

        public void AddWarningOnly(int id) {
            if (warnings_only == null)
                warnings_only = new List<int>();

            warnings_only.Add(id);
        }

        public bool IsWarningAsError(int code) {
            bool is_error = Compiler.options.warningLevel == WarningLevel.highest;

            // Check specific list
            if (warnings_as_error != null)
                is_error |= warnings_as_error.Contains(code);

            // Ignore excluded warnings
            if (warnings_only != null && warnings_only.Contains(code))
                is_error = false;

            return is_error;
        }

        public bool IsWarningEnabled(int code, int level) {
            if (warningLevel < (WarningLevel)level)
                return false;

            return !IsWarningDisabledGlobally(code);
        }

        public bool IsWarningDisabledGlobally(int code) {
            return disabledWarnings != null && disabledWarnings.Contains((ErrorCode)code);
        }

        #endregion

        #region 编译器设置

        /// <summary>
        /// 获取或设置当前的语言版本。
        /// </summary>
        public LanguageVersion languageVersion = LanguageVersion.latest;

        /// <summary>
        /// 获取或设置当前的运行时版本。
        /// </summary>
        public SdkVersion sdkVersion;

        /// <summary>
        /// 获取或设置最大的错误数。
        /// </summary>
        public int maxErrorCount = 100;

        /// <summary>
        /// 获取或设置当前的警告等级。
        /// </summary>
        public WarningLevel warningLevel = WarningLevel.high;

        /// <summary>
        /// 获取或设置禁用的警告。
        /// </summary>
        public HashSet<ErrorCode> disabledWarnings;

        /// <summary>
        /// 显示错误提示时使用的跟路径。
        /// </summary>
        public string rootPath;

        /// <summary>
        /// 获取或设置依赖的库文件。
        /// </summary>
        public List<ImportedLibarayInfo> importedLibs = new List<ImportedLibarayInfo>();

        /// <summary>
        /// 获取或设置目前是否正在编译系统库。
        /// </summary>
        public bool isCompilingCoreLib = true;

        #endregion

        #region 输入输出

        /// <summary>
        /// 获取或设置当前用于编译的源文件路径。
        /// </summary>
        public List<string> sourceFiles = new List<string>();

        /// <summary>
        /// 获取或设置所有源文件的编码。
        /// </summary>
        public Encoding sourceEncoding;

        /// <summary>
        /// 获取或设置文档的编码。
        /// </summary>
        public Encoding docEncoding;

        /// <summary>
        /// 获取或设置生成的二进制文件路径。
        /// </summary>
        public string outputPath;

        /// <summary>
        /// 获取或设置生成的调试信息文件路径。
        /// </summary>
        public string debugOutputPath;

        /// <summary>
        /// 获取或设置保存的文档文件路径。
        /// </summary>
        public string docOutputPath = String.Empty;

        /// <summary>
        /// 获取或设置编译使用的缓存文件夹。
        /// </summary>
        public string tempPath;

        #endregion

        #region 语法解析

        /// <summary>
        /// 获取或设置是否禁止省略条件表达式的括号。
        /// </summary>
        public bool disallowMissingParentheses;

        /// <summary>
        /// 获取或设置是否禁止省略语句后的分号。
        /// </summary>
        public bool disallowMissingSemicolons;

        /// <summary>
        /// 获取或设置当前预设值的所有宏。
        /// </summary>
        public HashSet<string> defines = new HashSet<string>() {
            "Teal",
            "TealCompiler",
            "TealCompiler1"
        };

        #endregion

        #region 语义解析

        /// <summary>
        /// 获取或设置是否禁止使用无法推导类型的 var 。
        /// </summary>
        public bool disallowVarAsObject = true;

        /// <summary>
        /// 获取或设置是否禁止省略函数主体。
        /// </summary>
        public bool disallowMissingFuncBody;

        /// <summary>
        /// 获取或设置是否禁止不安全代码。
        /// </summary>
        public bool disallowUnsafeCode;

        #endregion

        #region 代码生成

        /// <summary>
        /// 获取或设置编译的目标类型。
        /// </summary>
        public CompileTargetType targetType = CompileTargetType.win32Console;

        /// <summary>
        /// 获取或设置编译的目标平台。
        /// </summary>
        public CompileTargetPlatform targetPlatform = CompileTargetPlatform.all;

        /// <summary>
        /// 获取或设置当前编译器内嵌的资源文件。
        /// </summary>
        public Dictionary<string, string> embedResources;

        /// <summary>
        /// 获取或设置当前编译器的优化等级。
        /// </summary>
        public OptimizeLevel optimize;

        /// <summary>
        /// 获取或设置当前的主类。空表示全局。
        /// </summary>
        public string mainClass;

        /// <summary>
        /// 获取当前内嵌的 WIN32 资源文件。
        /// </summary>
        public string win32Resource;

        /// <summary>
        /// 获取当前内嵌的 WIN32 图标。
        /// </summary>
        public string win32Icon;

        #endregion

    }

    /// <summary>
    /// 表示对编译目标类型的枚举。
    /// </summary>
    public enum CompileTargetType {

        /// <summary>
        /// 编译为库文件。
        /// </summary>
        lib,

        /// <summary>
        /// 编译为控制台程序。
        /// </summary>
        console,

        /// <summary>
        /// 编译为应用程序。
        /// </summary>
        app,

        /// <summary>
        /// 编译为网站。
        /// </summary>
        web,

        /// <summary>
        /// 编译为 win32 控制台程序。
        /// </summary>
        win32Console,

        /// <summary>
        /// 编译为 win32 应用程序。
        /// </summary>
        win32App,

        /// <summary>
        /// 编译为 win32 动态链接库（dll）。
        /// </summary>
        win32Lib
    }

    /// <summary>
    /// 表示编译的目标平台。
    /// </summary>
    public enum CompileTargetPlatform {

        /// <summary>
        /// 支持所有平台。
        /// </summary>
        all,

        /// <summary>
        /// 支持所有平台。为 32 位平台优化。
        /// </summary>
        all32Preferred,

        /// <summary>
        /// 仅支持 arm 处理器。
        /// </summary>
        arm,

        /// <summary>
        /// 仅支持 x86 处理器。
        /// </summary>
        x86,

        /// <summary>
        /// 仅支持 x64 处理器。
        /// </summary>
        x64,
        ia64
    }

    /// <summary>
    /// 表示语言版本。
    /// </summary>
    public enum LanguageVersion {

        /// <summary>
        /// 版本 1。
        /// </summary>
        v1 = 1,

        /// <summary>
        /// 最新版本。
        /// </summary>
        latest = 128,

        ISO_1 = 1,
        ISO_2 = 2,
        V_3 = 3,
        V_4 = 4,
        V_5 = 5,
        V_6 = 6,
    }

    /// <summary>
    /// 表示运行时版本。
    /// </summary>
    public enum SdkVersion {

        /// <summary>
        /// 最新版本。
        /// </summary>
        latest = 128,

        /// <summary>
        /// 版本 1。
        /// </summary>
        v1 = 1,

        /// <summary>
        /// 版本 2。
        /// </summary>
        v2,

        /// <summary>
        /// 版本 3。
        /// </summary>
        v4,
    }

    /// <summary>
    /// 表示一个警告等级。
    /// </summary>
    public enum WarningLevel {

        /// <summary>
        /// 最低。所有警告都被忽略。
        /// </summary>
        lowest = 0,

        /// <summary>
        /// 较低。只提示重要警告。
        /// </summary>
        low = 1,

        /// <summary>
        /// 正常。提示大部分警告。
        /// </summary>
        normal = 2,

        /// <summary>
        /// 较高。提示所有警告。
        /// </summary>
        high = 3,

        /// <summary>
        /// 最高。所有警告都被作为错误处理。
        /// </summary>
        highest = 4,

    }

    /// <summary>
    /// 表示一个代码优化等级。
    /// </summary>
    public enum OptimizeLevel {

        /// <summary>
        /// 无任何优化。
        /// </summary>
        none = 0,

        /// <summary>
        /// 普通优化。
        /// </summary>
        basic = 1,

        /// <summary>
        /// 全部优化。此选项较费性能。
        /// </summary>
        all = 3,

    }

    /// <summary>
    /// 表示一个依赖的库文件。
    /// </summary>
    public struct ImportedLibarayInfo {

        /// <summary>
        /// 获取导入使用的别名。
        /// </summary>
        public string alias;

        /// <summary>
        /// 获取导入的库路径。
        /// </summary>
        public string path;

    }

}